﻿/********************************************************************************
** 作者： Mick
** 邮箱： zheng_jinfan@126.com
** 主页： http://www.zhengjinfan.cn
** 创始时间：2016-2-17
** 描述：
**      [辅助类]采集操作辅助类
*********************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using BestEasyCMS.Framework.Extension;

namespace BestEasyCMS.Framework.Util
{
    /// <summary>
    /// [辅助类]采集操作辅助类
    /// </summary>
    public class CollectionUtils
    {
        /// <summary>
        /// IList泛型集合转换成 DataSet
        /// </summary>
        /// <param name="list">泛型集合</param>
        /// <returns>DataSet</returns>
        public static DataSet ListToDataSet<T>(IList<T> list)
        {
            if (list == null || list.Count <= 0)
            {
                return null;
            }

            var ds = new DataSet();
            var dt = new DataTable(typeof (T).Name);

            var myPropertyInfo = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var t in list)
            {
                if (t == null)
                {
                    continue;
                }

                var row = dt.NewRow();

                for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                {
                    var pi = myPropertyInfo[i];

                    var name = pi.Name;

                    if (dt.Columns[name] == null)
                    {
                        var column = new DataColumn(name, pi.PropertyType);
                        dt.Columns.Add(column);
                    }

                    row[name] = pi.GetValue(t, null);
                }

                dt.Rows.Add(row);
            }

            ds.Tables.Add(dt);

            return ds;
        }

        /// <summary>
        ///  IList泛型集合转换成 DataTable
        /// </summary>
        /// <typeparam name="T">泛型类</typeparam>
        /// <param name="list">泛型集合</param>
        /// <returns>DataTable</returns>
        public static DataTable ListToDataTable<T>(IList<T> list)
        {
            if (list == null || list.Count <= 0)
            {
                return null;
            }
            var dt = new DataTable(typeof (T).Name);

            var myPropertyInfo = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var t in list)
            {
                if (t == null)
                {
                    continue;
                }

                var row = dt.NewRow();

                for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                {
                    var pi = myPropertyInfo[i];

                    var name = pi.Name;

                    if (dt.Columns[name] == null)
                    {
                        var column = new DataColumn(name, pi.PropertyType);
                        dt.Columns.Add(column);
                    }

                    row[name] = pi.GetValue(t, null);
                }

                dt.Rows.Add(row);
            }
            return dt;
        }

        #region 获取远程文件源代码

        /// <summary>
        /// 获取远程文件源代码
        /// </summary> 
        /// <param name="url"> 远程url地址</param>
        /// <param name="enCodeType">编码方式</param>
        /// <returns>网页源代码</returns>
        public string GetHttpPageCode(string url, Encoding enCodeType)
        {
            string strResult;
            if (url.Length < 10)
                return "$UrlIsFalse";
            try
            {
                var myWebClient = new WebClient
                {
                    Credentials = CredentialCache.DefaultCredentials,
                    Encoding = enCodeType
                };
                strResult = myWebClient.DownloadString(url);
            }
            catch (Exception)
            {
                strResult = "$GetFalse";
            }
            return strResult;
        }

        #endregion

        #region 根据表达式来截取字段

        /// <summary>
        /// 根据表达式来截取字段
        /// </summary>
        /// <param name="pageStr">原字符串</param>
        /// <param name="strStart">截取字符开始</param>
        /// <param name="strEnd">截取字符结束</param>
        /// <param name="inStart">是否包含strStart,false是不包含</param>
        /// <param name="inEnd">是否包含strEnd,false是不包含</param>
        /// <returns>截取后的字符串</returns>
        public string GetBody(string pageStr, string strStart, string strEnd, bool inStart, bool inEnd)
        {
            pageStr = pageStr.Trim();
            var start = pageStr.IndexOf(strStart, StringComparison.Ordinal);
            if (strStart.Length == 0 || start < 0)
                return "$StartFalse";
            pageStr = pageStr.Substring(start + strStart.Length, pageStr.Length - start - strStart.Length);
            var end = pageStr.IndexOf(strEnd, StringComparison.Ordinal);
            if (strEnd.Length == 0 || end < 0)
                return "$EndFalse";
            var strResult = pageStr.Substring(0, end);
            if (inStart)
                strResult = strStart + strResult;
            if (inEnd)
                strResult += strEnd;
            return strResult.Trim();
        }

        #endregion

        #region 根据正则获取链接地址

        /// <summary>
        /// 根据正则获取链接地址
        /// </summary>
        /// <param name="pageStr">原字符串</param>
        /// <param name="strStart">链接开始</param>
        /// <param name="strEnd">连接结束</param>
        /// <returns>链接地址集合</returns>
        public ArrayList GetLinkArray(string pageStr, string strStart, string strEnd)
        {
            var linkArray = new ArrayList();
            var start = pageStr.IndexOf(strStart, StringComparison.Ordinal);
            if (strStart.Length == 0 || start < 0)
            {
                linkArray.Add("$StartFalse");
                return null;
            }
            var end = pageStr.IndexOf(strEnd, StringComparison.Ordinal);
            if (strEnd.Length == 0 || end < 0)
            {
                linkArray.Add("$EndFalse");
                return null;
            }
            var myRegex = new Regex(@"(" + strStart + ").+?(" + strEnd + ")", RegexOptions.IgnoreCase);
            var matches = myRegex.Matches(pageStr);
            foreach (Match match in matches)
            {
                if (!linkArray.Contains(match.ToStr().ToLower()))
                    linkArray.Add(match.ToStr().ToLower());
            }
            if (linkArray.Count == 0)
            {
                linkArray.Add("$NoneLink");
                return null;
            }
            for (var i = 0; i < linkArray.Count; i++)
            {
                var tempStr = linkArray[i].ToString();
                tempStr = tempStr.Replace(strStart, "");
                tempStr = tempStr.Replace(strEnd, "");
                linkArray[i] = tempStr;
            }
            return linkArray;
        }

        #endregion

        #region 获取字符串图片并保存

        /// <summary>
        /// 获取字符串图片并保存
        /// </summary>
        /// <param name="pageStr">字符串</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="webUrl">指定网站url</param>
        /// <param name="isSave">是否保存图片</param>
        /// <returns>图片集合</returns>
        public ArrayList ReplaceSaveRemoteFile(string pageStr, string savePath, string webUrl, string isSave)
        {
            var replaceArray = new ArrayList();
            var imgReg = new Regex(@"<img.+?[^\>]>", RegexOptions.IgnoreCase);
            var matches = imgReg.Matches(pageStr);
            var tempStr = string.Empty;
            foreach (Match match in matches)
            {
                if (tempStr != string.Empty)
                    tempStr += "$Array$" + match;
                else
                    tempStr = match.ToString();
            }
            var tempArr = tempStr.Split(new[] {"$Array$"}, StringSplitOptions.None);
            tempStr = string.Empty;
            imgReg = new Regex(@"src\s*=\s*.+?\.(gif|jpg|bmp|jpeg|psd|png|svg|dxf|wmf|tiff)", RegexOptions.IgnoreCase);
            foreach (var t in tempArr)
            {
                matches = imgReg.Matches(t);
                foreach (Match match in matches)
                {
                    if (tempStr != string.Empty)
                        tempStr += "$Array$" + match;
                    else
                        tempStr = match.ToString();
                }
            }
            if (tempStr.Length > 0)
            {
                imgReg = new Regex(@"src\s*=\s*", RegexOptions.IgnoreCase);
                tempStr = imgReg.Replace(tempStr, "");
            }
            if (tempStr.Length == 0)
            {
                replaceArray.Add(pageStr);
                return replaceArray;
            }
            tempStr = tempStr.Replace("\"", "");
            tempStr = tempStr.Replace("'", "");
            tempStr = tempStr.Replace(" ", "");
            //去掉重复图片
            tempArr = tempStr.Split(new[] {"$Array$"}, StringSplitOptions.None);
            tempStr = string.Empty;
            foreach (var t in tempArr)
            {
                if (tempStr.IndexOf(t, StringComparison.Ordinal) == -1)
                    tempStr += "$Array$" + t;
            }
            tempStr = tempStr.Substring(7);
            tempArr = tempStr.Split(new[] {"$Array$"}, StringSplitOptions.None);
            var imageArr = string.Empty;
            for (var i = 0; i < tempArr.Length; i++)
            {
                imgReg = new Regex(tempArr[i]);
                var remoteFileUrl = DefiniteUrl(tempArr[i], webUrl);
                if (isSave == "1")
                {
                    var imgPath = HttpContext.Current.Server.MapPath(savePath + "/" + GetDateDir());
                    if (!Directory.Exists(imgPath))
                    {
                        Directory.CreateDirectory(imgPath);
                    }
                    var fileType = remoteFileUrl.Substring(remoteFileUrl.LastIndexOf('.'));
                    var filename = GetDateFile();
                    filename += fileType;
                    if (SavePhoto(imgPath + "/" + filename, remoteFileUrl))
                    {
                        remoteFileUrl = savePath + "/" + GetDateDir() + "/" + filename;
                    }
                }
                pageStr = imgReg.Replace(pageStr, remoteFileUrl);
                if (i == 0)
                {
                    imageArr = remoteFileUrl;
                }
                else
                    imageArr += "|||" + remoteFileUrl;
            }
            replaceArray.Add(pageStr);
            replaceArray.Add(imageArr);
            return replaceArray;
        }

        #endregion

        #region 相对路径转换绝对路径

        /// <summary>
        /// 相对路径转换绝对路径
        /// </summary>
        /// <param name="primitiveUrl">要转换地址</param>
        /// <param name="consultUrl">指定网站地址</param>
        /// <returns>绝对路径</returns>
        public string DefiniteUrl(string primitiveUrl, string consultUrl)
        {
            if (consultUrl.Substring(0, 7) != "http://")
                consultUrl = "http://" + consultUrl;
            consultUrl = consultUrl.Replace(@"\", "/");
            consultUrl = consultUrl.Replace("://", @":\\");
            primitiveUrl = primitiveUrl.Replace(@"\", "/");

            if (consultUrl.Substring(consultUrl.Length - 1) != "/") //如果没有/加个/
            {
                if (consultUrl.IndexOf('/') > 0)
                {
                    if (
                        consultUrl.Substring(consultUrl.LastIndexOf("/", StringComparison.Ordinal),
                                             consultUrl.Length - consultUrl.LastIndexOf("/", StringComparison.Ordinal)).IndexOf('.') == -1)
                        consultUrl += "/";
                }
                else
                    consultUrl += "/";
            }
            var conArray = consultUrl.Split('/');
            var returnStr = string.Empty;
            var pi = 0;
            if (primitiveUrl.Substring(0, 7) == "http://")
                returnStr = primitiveUrl.Replace("://", @":\\");
            else if (primitiveUrl.Substring(0, 1) == "/")
                returnStr = conArray[0] + primitiveUrl;
            else if (primitiveUrl.Substring(0, 2) == "./")
            {
                primitiveUrl = primitiveUrl.Substring(2, primitiveUrl.Length - 2);
                if (consultUrl.Substring(consultUrl.Length - 1) == "/")
                    returnStr = consultUrl + primitiveUrl;
                else
                    returnStr = consultUrl.Substring(0, consultUrl.LastIndexOf('/')) + primitiveUrl;
            }
            else if (primitiveUrl.Substring(0, 3) == "../")
            {
                while (primitiveUrl.Substring(0, 3) == "../")
                {
                    primitiveUrl = primitiveUrl.Substring(3);
                    pi++;
                }
                for (var i = 0; i < conArray.Length - 1 - pi; i++)
                {
                    if (returnStr.Length > 0)
                        returnStr = returnStr + conArray[i];
                    else
                        returnStr = conArray[i];
                }
                returnStr = returnStr + primitiveUrl;
            }
            else
            {
                if (primitiveUrl.IndexOf('/') > -1)
                {
                    var priArray = primitiveUrl.Split('/');
                    if (priArray[0].IndexOf('.') > -1)
                    {
                        if (primitiveUrl.Substring(primitiveUrl.Length - 1) == "/")
                            return "http://" + primitiveUrl;
                        {
                            if (priArray[priArray.Length - 1].IndexOf('.') > -1)
                                returnStr = "http:\\" + primitiveUrl;
                            else
                                returnStr = "http:\\" + primitiveUrl + "/";
                        }
                    }
                    else
                    {
                        if (consultUrl.Substring(consultUrl.Length - 1) == "/")
                            returnStr = consultUrl + primitiveUrl;
                        else
                            returnStr = consultUrl.Substring(0, consultUrl.LastIndexOf('/')) + primitiveUrl;
                    }
                }
                else
                {
                    if (primitiveUrl.IndexOf('.') > -1)
                    {
                        var lastUrl = consultUrl.Substring(consultUrl.LastIndexOf('.'));
                        if (consultUrl.Substring(consultUrl.Length - 1) == "/")
                        {
                            if (lastUrl == "com" || lastUrl == "cn" || lastUrl == "net" || lastUrl == "org")
                                returnStr = "http:\\" + primitiveUrl + "/";
                            else
                                returnStr = consultUrl + primitiveUrl;
                        }
                        else
                        {
                            if (lastUrl == "com" || lastUrl == "cn" || lastUrl == "net" || lastUrl == "org")
                                returnStr = "http:\\" + primitiveUrl + "/";
                            else
                                returnStr = consultUrl.Substring(0, consultUrl.LastIndexOf('/')) + "/" + primitiveUrl;
                        }
                    }
                    else
                    {
                        if (consultUrl.Substring(consultUrl.Length - 1) == "/")
                            returnStr = consultUrl + primitiveUrl + "/";
                        else
                            returnStr = consultUrl.Substring(0, consultUrl.LastIndexOf('/')) + "/" + primitiveUrl + "/";
                    }
                }
            }

            if (returnStr.Substring(0, 1) == "/")
                returnStr = returnStr.Substring(1);
            if (returnStr.Length > 0)
            {
                returnStr = returnStr.Replace("//", "/");
                returnStr = returnStr.Replace(@":\\", "://");
            }
            else
                returnStr = "$False";
            return returnStr;
        }

        #endregion

        #region 保存图片

        /// <summary>
        /// 保存图片
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="remoteFileUrl">远程图片url地址</param>
        /// <returns>true成功，false失败</returns>
        public bool SavePhoto(string fileName, string remoteFileUrl)
        {
            try
            {
                var request = WebRequest.Create(remoteFileUrl);
                request.Timeout = 20000;
                var stream = request.GetResponse().GetResponseStream();
                if (stream == null) return true;
                var getImage = Image.FromStream(stream);
                getImage.Save(fileName);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        #endregion

        #region 文件创建

        /// <summary>
        /// 根据日期得到目录名
        /// </summary>
        /// <returns></returns>
        public string GetDateDir()
        {
            return DateTime.Now.ToString("yyyyMMdd");
        }

        /// <summary>
        /// 根据时间得到文件名
        /// </summary>
        /// <returns></returns>
        public string GetDateFile()
        {
            return DateTime.Now.ToString("HHmmssff");
        }

        #endregion

        #region 过滤代码中的标签

        /// <summary>
        /// 过滤代码中的标签
        /// </summary>
        /// <param name="html">代码</param>
        /// <param name="tagName">标签</param>
        /// <param name="fType">过滤类型</param>
        /// <returns></returns>
        public string ScriptHtml(string html, string tagName, int fType)
        {
            Regex myReg;
            switch (fType)
            {
                case 1:
                    myReg = new Regex("<" + tagName + "([^>])*>", RegexOptions.IgnoreCase);
                    html = myReg.Replace(html, "");
                    break;
                case 2:
                    myReg = new Regex("<" + tagName + "([^>])*>.*?</" + tagName + "([^>])*>", RegexOptions.IgnoreCase);
                    html = myReg.Replace(html, "");
                    break;
                case 3:
                    myReg = new Regex("<" + tagName + "([^>])*>", RegexOptions.IgnoreCase);
                    html = myReg.Replace(html, "");
                    myReg = new Regex("</" + tagName + "([^>])*>", RegexOptions.IgnoreCase);
                    html = myReg.Replace(html, "");
                    break;
            }
            return html;
        }

        #endregion

        #region 过滤html标签

        /// <summary>
        /// 过滤html标签
        /// </summary>
        /// <param name="html">原始Html文本</param>
        /// <returns>去掉Html标记后的文本</returns>
        public string HtmlScript(string html)
        {
            html = Regex.Replace(html, "<[^>]*>", "");
            return html;
        }

        #endregion

        #region 执行正则提取出值

        /// <summary>
        /// 执行正则提取出值
        /// </summary>
        /// <param name="regex">正则表达式</param>
        /// <param name="html">Html源代码</param>
        /// <returns>匹配文本</returns>
        public string GetRegValue(string regex, string html)
        {
            //string resString = "";
            //Regex reg = new Regex(RegexString, RegexOptions.IgnoreCase);
            //MatchCollection matches = reg.Matches(html);
            //foreach (Match match in matches)
            //{
            //    resString += match.Groups[1].Value;
            //}
            return GetRegValue(regex, html, -1);
        }

        #endregion

        #region 执行正则提取出值

        /// <summary>
        /// 执行正则提取出值
        /// </summary>
        /// <param name="regex">正则表达式</param>
        /// <param name="html">Html源代码</param>
        /// <param name="num"> </param>
        /// <returns>匹配文本</returns>
        public string GetRegValue(string regex, string html, int num)
        {
            var resString = "";
            var reg = new Regex(regex, RegexOptions.IgnoreCase);
            var matches = reg.Matches(html);
            var i = 0;
            foreach (Match match in matches)
            {
                if (num != -1)
                {
                    if (i < num) //防止地址重复
                    {
                        i++;
                        // resString += match.Groups[1].Value;
                        resString += match.Value;
                    }
                }
                else
                {
                    // resString += match.Groups[1].Value;
                    resString += match.Value;
                }
            }
            return resString;
        }

        #endregion
    }
}